import aiohttp
import asyncio
import time
import hmac
import base64
import json
from typing import Dict, List, Optional
from loguru import logger
from .config import ConfigManager

class BitgetAPIClient:
    BASE_URL = "https://api.bitget.com"
    
    def __init__(self):
        self.config = ConfigManager()
        self.api_key, self.api_secret, self.passphrase = self.config.get_api_key()
        self.session = None
        self.max_retries = 3
        self.retry_delay = 1  # 秒
        
    async def __aenter__(self):
        self.session = aiohttp.ClientSession()
        return self
        
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if self.session:
            await self.session.close()
            
    def _sign(self, method: str, path: str, params: Dict = None) -> Dict:
        """生成签名"""
        timestamp = str(int(time.time() * 1000))
        message = timestamp + method.upper() + path
        if params:
            message += json.dumps(params)
            
        signature = base64.b64encode(
            hmac.new(
                self.api_secret.encode(),
                message.encode(),
                'sha256'
            ).digest()
        ).decode()
        
        return {
            "ACCESS-KEY": self.api_key,
            "ACCESS-SIGN": signature,
            "ACCESS-TIMESTAMP": timestamp,
            "ACCESS-PASSPHRASE": self.passphrase,
            "Content-Type": "application/json"
        }
        
    async def _request(self, method: str, path: str, params: Dict = None) -> Dict:
        """发送请求"""
        url = self.BASE_URL + path
        headers = self._sign(method, path, params)
        
        for attempt in range(self.max_retries):
            try:
                async with self.session.request(
                    method,
                    url,
                    headers=headers,
                    json=params,
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as response:
                    if response.status == 200:
                        return await response.json()
                    else:
                        error_text = await response.text()
                        logger.error(f"API请求失败: {response.status} - {error_text}")
                        if attempt < self.max_retries - 1:
                            await asyncio.sleep(self.retry_delay * (attempt + 1))
                            continue
                        raise Exception(f"API请求失败: {response.status} - {error_text}")
                        
            except asyncio.TimeoutError:
                logger.error(f"请求超时: {url}")
                if attempt < self.max_retries - 1:
                    await asyncio.sleep(self.retry_delay * (attempt + 1))
                    continue
                raise
                
            except aiohttp.ClientError as e:
                logger.error(f"网络错误: {str(e)}")
                if attempt < self.max_retries - 1:
                    await asyncio.sleep(self.retry_delay * (attempt + 1))
                    continue
                raise
                
            except Exception as e:
                logger.error(f"请求失败: {str(e)}")
                if attempt < self.max_retries - 1:
                    await asyncio.sleep(self.retry_delay * (attempt + 1))
                    continue
                raise
                
    async def get_supported_coins(self) -> List[str]:
        """获取支持的币种列表"""
        return await self._request("GET", "/api/v2/spot/public/coins")
        
    async def get_coin_info(self, coin: str) -> Dict:
        """获取币种信息"""
        return await self._request("GET", f"/api/v2/spot/public/coins?coin={coin}")
        
    async def get_subaccount_assets(self) -> List[Dict]:
        """获取子账户资产"""
        return await self._request("GET", "/api/v2/spot/account/subaccount-assets")
        
    async def transfer_assets(self, from_user: str, to_user: str, coin: str, amount: str) -> Dict:
        """子母账户划转"""
        params = {
            "fromUserId": from_user,
            "toUserId": to_user,
            "fromType": "spot",
            "toType": "spot",
            "amount": amount,
            "coin": coin
        }
        return await self._request("POST", "/api/v2/spot/wallet/subaccount-transfer", params)
        
    async def withdraw(self, coin: str, address: str, chain: str, amount: float) -> Dict:
        """提币"""
        params = {
            "coin": coin,
            "address": address,
            "chain": chain,
            "amount": str(amount)
        }
        return await self._request("POST", "/api/v2/spot/wallet/withdrawal", params)
        
    async def place_order(self, symbol: str, side: str, order_type: str, size: str, price: Optional[str] = None) -> Dict:
        """下单"""
        params = {
            "symbol": symbol,
            "side": side,
            "orderType": order_type,
            "force": "gtc",
            "size": size
        }
        if price:
            params["price"] = price
        return await self._request("POST", "/api/v2/spot/trade/place-order", params)
        
    async def get_account_balance(self) -> Dict:
        """获取账户余额"""
        return await self._request("GET", "/api/v2/spot/account/assets")
        
    async def transfer(self, from_account: str, to_account: str, coin: str, amount: float) -> Dict:
        """划转"""
        params = {
            "fromAccount": from_account,
            "toAccount": to_account,
            "coin": coin,
            "amount": str(amount)
        }
        return await self._request("POST", "/api/v2/spot/account/transfer", params)
        
    async def create_order(self, symbol: str, side: str, order_type: str, price: str, size: str) -> Dict:
        """创建订单"""
        params = {
            "symbol": symbol,
            "side": side,
            "orderType": order_type,
            "price": price,
            "size": size
        }
        return await self._request("POST", "/api/v2/spot/trade/orders", params) 